package com.googlecode.jaks.swt;

import static com.googlecode.jaks.common.util.StringUtil.isEmpty;
import static com.googlecode.jaks.common.io.StreamUtil.transfer;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Locale;
import java.util.zip.GZIPInputStream;

import org.apache.tools.bzip2.CBZip2InputStream;
import org.apache.tools.tar.TarEntry;
import org.apache.tools.tar.TarInputStream;

import com.googlecode.jaks.common.io.NonClosingInputStream;

/**
 * 
 * @author Jason Smith
 * @requiresDependencyResolution compile
 * @goal install-artifact-from-http-tar
 * @phase package
 */
public class InstallArtifactFromHttpTarMojo extends InstallArtifactFromHttpMojo
{
	/**
	 * Regular expression identifying the path of the artifact within the archive.
	 * @parameter
	 */
	protected String path = null;
	
	/**
	 * Archive compression. This is normally assumed to be GZip ("gz"), but can
	 * also be empty to indicate no compression or "bz" for BZip2.
	 * <br/><strong>Default</strong>: <tt>gz</tt>
	 * @parameter
	 */
	protected String compression = "gz";

	@Override
	protected void processArchive(final File archive) throws FileNotFoundException, IOException 
	{
		if(isEmpty(path))
		{
			throw new IllegalArgumentException("Path within archive not specified.");
		}
		
		InputStream in = new BufferedInputStream(new FileInputStream(archive));
		try
		{
			if(!isEmpty(compression))
			{
				if(compression.toLowerCase(Locale.getDefault()).startsWith("gz"))
				{
					in = new GZIPInputStream(in);
				}
				else if(compression.toLowerCase(Locale.getDefault()).startsWith("bz"))
				{
					int c1 = in.read();
					int c2 = in.read();
					
					if(c1 != (int)'B' || c2 != (int)'z')
					{
						throw new IOException("Stream does not appear to be BZip2 encoded.");
					}
					
					in = new CBZip2InputStream(in);
				}
			}
			
			final TarInputStream tarIn = new TarInputStream(in);
			try
			{
				boolean foundOne = false;
				for(;;)
				{
					final TarEntry entry = tarIn.getNextEntry();
					try
					{
						if(entry == null)
						{
							break;
						}
						
						if(!isEmpty(entry.getName()) && entry.getName().matches(path))
						{
							foundOne = true;
							
							final File file = new File(getTargetDir(), 
									project.getArtifactId() + "-" + project.getVersion() + 
									(isEmpty(classifier) ? "" : "-"+classifier) +
									".jar");
							
							transfer(new NonClosingInputStream(tarIn), new BufferedOutputStream(new FileOutputStream(file)));
							
							if(!isEmpty(classifier))
							{
								this.attachArtifact(project, "jar", classifier, file);
							}
							
							break;
						}
					}
					finally
					{
						
					}
				}
				
				if(!foundOne)
				{
					throw new IllegalArgumentException("No match found for " + path);
				}
			}
			finally
			{
				tarIn.close();
			}
		}
		finally
		{
			in.close();
		}
	}
}
